package com.wolfword.common.util.password;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.wolfword.common.util.number.NumberSystemUtil;

/**
 * MD5加密类
 * 
 * @author ServerZhang
 * @date 2015年6月18日
 */
public class MD5Util {

	/**
	 * 使用MessageDigest的MD5加密
	 * 
	 * @param str
	 * @return
	 * @author ServerZhang
	 * @date 2015年6月18日
	 */
	public static String encrypt(String str) {
		String newStr = "";
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");// 申明使用MD5算法
			md5.update(str.getBytes());
			byte[] digest = md5.digest();
			// newStr = byte2Hex(digest);
			newStr = NumberSystemUtil.bytes2HexStr(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return newStr;
	}

	/**
	 * 文件MD5签名
	 * 已优化：分块签名，防止内存溢出
	 * @param file
	 * @return 文件签名信息
	 * @author ServerZhang
	 * @date 2017年11月30日
	 */
	public static String encrypt(File file) {
		if (!file.exists() || !file.isFile()) {
			return null;
		}
		FileInputStream fileInputStream = null;
		BufferedInputStream bufferedInputStream = null;
		String newStr = "";
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");// 申明使用MD5算法
			fileInputStream = new FileInputStream(file);
			bufferedInputStream = new BufferedInputStream(fileInputStream);

			int buf_size = 1024;
			byte[] buffer = new byte[buf_size];
			int len = 0;
			while (-1 != (len = bufferedInputStream.read(buffer, 0, buf_size))) {
				md5.update(buffer, 0, len);//分块签名，防止内存溢出
			}

			byte[] digest = md5.digest();
			newStr = NumberSystemUtil.bytes2HexStr(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return newStr;
	}

	/**
	 * 调用MyMD5.encrypt()方法进行多次加密
	 * 
	 * @param str
	 * @param num
	 * @return
	 * @author ServerZhang
	 * @date 2015年7月9日
	 */
	public static String circularlyEncrypt(String str, Integer num) {
		String newStr = str;
		for (int i = 0; i < num; i++) {
			newStr = MD5Util.encrypt(newStr);
		}
		return newStr;
	}

	/**
	 * 将字符数组转十六进制字符串
	 * 
	 * @param bytes
	 * @return
	 * @author ServerZhang
	 * @date 2015年6月18日
	 */
	@Deprecated
	private static String byte2Hex(byte[] bytes) {
		char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		StringBuffer sBuffer = new StringBuffer();
		for (byte byte0 : bytes) {
			sBuffer.append(hex[byte0 >>> 4 & 0xf]);// &0xf取二进制后四位
			sBuffer.append(hex[byte0 & 0xf]);
		}
		return sBuffer.toString();
	}

}